using System.Collections.Generic;
using Msic;
using Sirenix.OdinInspector;
using Sirenix.Serialization;
using UnityEngine;

namespace cmd
{
    [AssetList]
    public sealed class RandomLayerGenerateDataSO : SerializedScriptableObject
    {
        [field: OdinSerialize]
        public RandomLayerGenerateData RandomLayerGenerateData { get; private set; } = new();

        /// <summary>
        /// 根据权重随机抽选出一个Layer
        /// </summary>
        /// <returns>随机抽选出的Layer，如果列表为空则返回null</returns>
        public LevelLayerDataSO GetRandomLayer() => RandomLayerGenerateData.GetRandomLayer();
    }

    [System.Serializable]
    public class RandomLayerGenerateData
    {
        [field: OdinSerialize, ListDrawerSettings(CustomAddFunction = nameof(CustomAddFunction))]
        public List<RandomSingleLayerGenerateData> RandomSingleLayerGenerateDatas
        {
            get;
            private set;
        } = new();

        private RandomSingleLayerGenerateData CustomAddFunction => new() { Weight = 1 };

        /// <summary>
        /// 根据权重随机抽选出一个Layer
        /// </summary>
        /// <returns>随机抽选出的Layer，如果列表为空则返回null</returns>
        public LevelLayerDataSO GetRandomLayer()
        {
            if (RandomSingleLayerGenerateDatas == null || RandomSingleLayerGenerateDatas.Count == 0)
            {
                return null;
            }

            // 计算总权重并检查是否所有权重都是1
            int totalWeight = 0;
            bool allWeightsAreOne = true;
            foreach (var data in RandomSingleLayerGenerateDatas)
            {
                totalWeight += data.Weight;
                if (data.Weight != 1)
                {
                    allWeightsAreOne = false;
                    break;
                }
            }

            // 如果所有权重都是1，直接使用随机选择
            if (allWeightsAreOne)
            {
                return RandomSingleLayerGenerateDatas.GetRandomElement().LayerSO;
            }

            // 随机一个权重值
            int randomWeight = Random.Range(0, totalWeight);

            // 根据权重选择对应的Layer
            int currentWeight = 0;
            foreach (var data in RandomSingleLayerGenerateDatas)
            {
                currentWeight += data.Weight;
                if (randomWeight < currentWeight)
                {
                    return data.LayerSO;
                }
            }

            // 理论上不会执行到这里
            return RandomSingleLayerGenerateDatas[0].LayerSO;
        }
    }

    [System.Serializable]
    public readonly struct RandomLayerGenerateConfiguration
    {
        public enum LayerGenerateConfigurationMethod
        {
            UseSO = 1,
            UseInline = 2
        }

        [OdinSerialize, EnumToggleButtons, PropertyOrder(-10)]
        public LayerGenerateConfigurationMethod ConfigMethod { get; init; }

        [field: SerializeField, LabelText("随机层生成表SO")]
        [field: ShowIf(nameof(ConfigMethod), LayerGenerateConfigurationMethod.UseSO)]
        public RandomLayerGenerateDataSO RandomLayerGenerateDataSO { get; init; }

        [field: SerializeField, LabelText("随机层生成表")]
        [field: ShowIf(nameof(ConfigMethod), LayerGenerateConfigurationMethod.UseInline)]
        public RandomLayerGenerateData RandomLayerGenerateData { get; init; }

        public RandomLayerGenerateData Data =>
            ConfigMethod switch
            {
                LayerGenerateConfigurationMethod.UseSO
                    => RandomLayerGenerateDataSO.RandomLayerGenerateData,
                LayerGenerateConfigurationMethod.UseInline => RandomLayerGenerateData,
                _ => throw new System.NotImplementedException("意外的配置方式"),
            };
    }

    [System.Serializable]
    public readonly struct RandomSingleLayerGenerateData
    {
        [field: SerializeField]
        public int Weight { get; init; }

        [field: SerializeField]
        public LevelLayerDataSO LayerSO { get; init; }
    }
}
